/**************************
* @Summary atoi函数实现
* @Author 20009200303 赵传博
* @Date 2022/3/22
*****************************/

#include "AtoiUtil.h"
int AtoiUtil::myAtoi(string array) {
    int result = 0;
    bool isNegative = false;
    /**
     * 首先判断是16进制，8进制还是10进制，其次判断是否有正负号，之后讨论是否有错误的字符出现
     */
    if((array[0] == '0' && (array[1] == 'x' || array[1] == 'X')) || ((array[0] == '+' || array[0] == '-') && array[1] == '0' && (array[2] == 'x' || array[2] == 'X'))){
        if(array[0] == '-') isNegative = true;
        return hexToi(array, isNegative);
    }else if((array[0] == '0' && isdigit(array[1])) || ((array[0] == '+' || array[0] == '-') && array[1] == '0' && isdigit(array[2]))){
        if(array[0] == '-') isNegative = true;
        return octToi(array, isNegative);
    }
    if(array[0] == '+' || array[0] == '-'){
        if(array[0] == '-') isNegative = true;
        for(int i = 1; i < array.length(); ++i){
            if(!isdigit(array[i])){
                /* 这里要处理错误字符后面的位置，把他们删掉，就是除以进制的剩余长度次方，后面同理 */
                return isNegative? -result / (int)pow(10, array.length() - i) : result / (int)pow(10, array.length() - i);
            }
            int val = array[i] - '0';
            result += val * (int)pow(10, array.length() - i - 1);
        }
        return isNegative? -result : result;
    }else{
        for(int i = 0; i < array.length(); ++i){
            if(!isdigit(array[i])){
                return result / (int)pow(10, array.length() - i);//123a
            }
            int val = array[i] - '0';
            result += val * (int)pow(10, array.length() - i - 1);
        }
        return result;
    }
}


int AtoiUtil::octToi(string array, bool isNegative) {
    int result = 0;
    if(array[0] == '+' || array[0] == '-'){
        for(int i = 2; i < array.length(); ++i){
            if(!isdigit(array[i])){
                return isNegative? -result / (int)pow(8, array.length() - i) : result / (int)pow(8, array.length() - i);
            }
            int val = array[i] - '0';
            result += val * (int)pow(8, array.length() - i - 1);
        }
        return isNegative? -result : result;
    }else{
        for(int i = 1; i < array.length(); ++i){
            if(!isdigit(array[i])){
                return result / (int)pow(8, array.length() - i);
            }
            int val = array[i] - '0';
            result += val * (int)pow(8, array.length() - i - 1);
        }
        return result;
    }
}

int AtoiUtil::hexToi(string array, bool isNegative) {
    int result = 0;
    if(array[0] == '+' || array[0] == '-'){
        for(int i = 3; i < array.length(); ++i){
            /**
             * 由于16进制存在合法的字母，所以需要特判：
             *  既不是数字，也不在a-f,A-F区间内的字符为非法字符
             */
            if(!isdigit(array[i]) && !((array[i] >= 'a' && array[i] <= 'f') || (array[i] >= 'A' && array[i] <= 'F'))){
                return isNegative? -result / (int)pow(16, array.length() - i) : result / (int)pow(16, array.length() - i);
            }
            int val;
            if(isdigit(array[i])){
                val = array[i] - '0';
            }else{
                /* 对于合法的字母，转换时要分别赋值，下面同理 */
                if(array[i] >= 'a' && array[i] <= 'f'){
                    val = array[i] - 87;
                }else{ // A-F
                    val = array[i] - 55;
                }
            }
            result += val * (int)pow(16, array.length() - i - 1);
        }
        return isNegative? -result : result;
    }else{
        for(int i = 2; i < array.length(); ++i){
            if(!isdigit(array[i]) && !((array[i] >= 'a' && array[i] <= 'f') || (array[i] >= 'A' && array[i] <= 'F'))){
                return result / (int)pow(16, array.length() - i);
            }
            int val;
            if(isdigit(array[i])){
                val = array[i] - '0';
            }else{
                if(array[i] >= 'a' && array[i] <= 'f'){
                    val = array[i] - 87;
                }else{
                    val = array[i] - 55;
                }
            }
            result += val * (int)pow(16, array.length() - i - 1);
        }
        return result;
    }
}